Skip to content

feat!: switch monorepo from npm to pnpm#1298

Merged
sorccu merged 47 commits into
next/v8from
simo/sim-244-switch-cli-from-npm-to-pnpm
May 20, 2026
Merged

feat!: switch monorepo from npm to pnpm#1298
sorccu merged 47 commits into
next/v8from
simo/sim-244-switch-cli-from-npm-to-pnpm

Conversation

@sorccu
Copy link
Copy Markdown
Member

@sorccu sorccu commented May 13, 2026

Summary

  • Switch monorepo from npm to pnpm
    • Replace package-lock.json with pnpm-lock.yaml and add pnpm-workspace.yaml
    • Update all CI workflows, npm scripts, and simple-git-hooks to use pnpm
    • Add pnpm.onlyBuiltDependencies for esbuild and simple-git-hooks
  • Add string-width and ast-types as explicit dependencies (phantom deps under npm)
  • Decouple skills/ sync from prepare lifecycle (pnpm run sync:skills)
  • Introduce FixtureTemplate for test fixtures
    • Pre-install dependencies once via packed tarball, share across sandboxes via symlinks
    • Migrate all unit and e2e tests to use templates
    • Replace runChecklyCli with FixtureSandbox + runCheckly helper
  • Stop injecting jiti into scaffolded project dependencies (now bundled by CLI)
  • Split e2e CI jobs per package to prevent parallel rebuild conflicts
  • Various e2e test fixes for pnpm compatibility

Supersedes #1299.
Depends on: #1297

Test plan

  • All unit tests pass (Ubuntu + Windows)
  • All e2e tests pass (Ubuntu)
  • All e2e tests pass (Windows)
  • pnpm install --frozen-lockfile succeeds
  • Lint passes
  • pnpm run sync:skills produces correct output

🤖 Generated with Claude Code

sorccu and others added 2 commits May 13, 2026 20:29
BREAKING CHANGE: The project now uses pnpm as its package manager.

- Replace package-lock.json with pnpm-lock.yaml (imported via pnpm import)
- Add pnpm-workspace.yaml for workspace configuration
- Update all CI workflows to use pnpm
- Update all npm scripts to use pnpm equivalents
- Update simple-git-hooks to use pnpm exec
- Add pnpm.onlyBuiltDependencies for esbuild and simple-git-hooks
- Replace fixture npm lockfiles with pnpm lockfiles
- Update test expectations for pnpm-lock.yaml in bundled file lists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sorccu sorccu force-pushed the simo/sim-244-switch-cli-from-npm-to-pnpm branch from 54f503e to e001bed Compare May 13, 2026 11:30
sorccu and others added 13 commits May 13, 2026 20:38
These were phantom dependencies (transitive via recast and other packages)
that worked with npm's flat node_modules but fail under pnpm's strict
dependency resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set child-concurrency=1 in .npmrc so pnpm runs workspace prepare
scripts sequentially. Remove the redundant `pnpm -r run prepare`
from the root prepare script (pnpm already runs each package's
prepare hook) and move prepare:ai-context to postprepare so it
runs after all packages are built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test injected initializeGit=true but didn't account for when
.git already existed (skipping the prompt). Change to not init git
since it's not what the test is verifying, and add the missing
askCopyPlaywrightProject prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cies

jiti is now bundled internally by the CLI and no longer needed as a
user-facing dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixtures now detect pnpm as the package manager, so the generated
testCommand is 'pnpm playwright test' instead of 'npx playwright test'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the root-level skills/ copy from a postprepare lifecycle hook to
an explicit sync:skills script. This eliminates the cross-package
dependency between root and packages/cli during pnpm install, removing
the need for child-concurrency=1 in .npmrc.

The AI context is still built as part of packages/cli's prepare script
(needed for the published tarball), but the root no longer races to
copy from its output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce FixtureTemplate to pre-install dependencies once and share
them across fixtures via symlinks, reducing pnpm install calls from
53 to 1.

- Add FixtureTemplate class that caches pre-installed node_modules
- Add vitest globalSetup to build the playwright template once
- Migrate playwright-check, parse-files tests to use template
- Set installPackages: false for fixtures with no deps (agentic-check,
  api-check, browser-check, project-parser)
- Symlink workspace checkly package into all fixture node_modules
- Remove injectPackedSelf (dead code) and pnpm pack from test scripts
- Remove accidentally committed node_modules from test-bundling and
  test-shared-bundling fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Share a single playwright install across all e2e fixture sandboxes
via symlinked node_modules. Fixtures with no dependencies use
installPackages: false instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace npx with pnpm in e2e test runners for consistency with the
pnpm-based fixtures. Add pnpm-lock.yaml to all e2e fixtures so
detectPackageManager reliably identifies pnpm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add FixtureTemplate.use() which looks up a cached template by name,
falling back to an env var set by globalSetup for cross-process
communication. Test files now pass template: 'playwright' as a string
instead of managing FixtureTemplate.create() calls directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@checkly checkly deleted a comment from github-actions Bot May 14, 2026
@checkly checkly deleted a comment from github-actions Bot May 14, 2026
sorccu and others added 10 commits May 14, 2026 17:48
…test

The test-pwt-native fixture pins @playwright/test to 1.53.1. The shared
playwright template installs ^1.59.1 which resolves to a newer version,
causing a version mismatch error at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sequential pnpm installs let the second template reuse packages
cached by the first (e.g. playwright-core), avoiding redundant
downloads on CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make source param optional (empty sandbox when omitted)
- Add 'bare' template (checkly only, no other deps)
- Fix Windows .bin by writing a .cmd shim instead of a symlink
- Replace runChecklyCli with checklyEnv + runCheckly helpers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dbox

Replace the raw child_process.spawn-based runChecklyCli with
FixtureSandbox + runCheckly helper across all 21 e2e test files.

Tests now use pnpm checkly via the .bin symlink instead of spawning
bin/run directly, which fixes Windows module resolution issues with
pnpm's node_modules layout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pnpm requires a package.json in the working directory. When no source
is provided, write a minimal one so pnpm checkly can run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- destroy: wrong project name exits 0, not failure
- login: remove trailing newline assertion (oclif line-wrapping)
- switch: remove trailing newline assertion
- env.rm: add explicit timeout for interactive prompt test
- Add missing package.json to fixtures that lacked one
- Write package.json in sourceless sandboxes for pnpm compat

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use CHECKLY_CLI_MODE=interactive instead of unsetting CI, since
the CLI also checks GITHUB_ACTIONS and other CI-specific env vars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, oclif's module-loader uses require() to load the custom
help class. Without the .js extension, require() fails to resolve
the module in an ESM package because Node.js doesn't auto-append
extensions for require() in "type": "module" packages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, pnpm's import() of oclif command modules fails with
MODULE_NOT_FOUND even when the files exist. Bypass pnpm's execution
layer by invoking node with the bin/run path directly, matching the
behavior of the old runChecklyCli helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sorccu and others added 5 commits May 15, 2026 15:43
On Windows, Node.js import() fails when resolving through NTFS
junctions. Use CLI_PACKAGE_ROOT directly to avoid junction traversal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use extendEnv: false so the CLI subprocess gets only explicitly passed
env vars, matching the old child_process.spawn behavior. This prevents
CI runner env vars from interfering with the CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests using fixt.run directly need checklyEnv() to provide API keys
and other required env vars when extendEnv is false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NTFS junctions cause Node.js ESM import() to fail when resolving
modules through the junction. Regular dir symlinks work correctly
on GitHub Actions runners which have the required permissions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add uuid to the playwright template (used by deploy-project fixture).
Switch sync-playwright tests from bare to playwright template (fixture
loads playwright.config.ts which imports @playwright/test).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sorccu sorccu force-pushed the simo/sim-244-switch-cli-from-npm-to-pnpm branch from f4b4f64 to dd55f12 Compare May 19, 2026 11:25
sorccu and others added 9 commits May 20, 2026 00:04
Matches the old runChecklyCli behavior which used shell: true on
Windows for cmd.exe to handle process execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unit tests use pnpm checkly and pass on Windows. The node bin/run
approach fails because oclif's CJS module-loader can't import()
ESM command files using Windows absolute paths. With dir symlinks
(not junctions) now in place, pnpm checkly should work correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Node.js on Windows needs system env vars (SYSTEMROOT, etc.) for
module resolution. Stripping the env caused import() to fail for
some files. Use the default extendEnv: true and rely on
CHECKLY_CLI_MODE: 'interactive' to handle CI detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…king

Windows CI runners have broken pnpm junctions that cause import() to
fail. Install the packed CLI tarball into each FixtureTemplate via
pnpm install, giving real file copies instead of junctions.

- Add pnpm pack back to test scripts
- FixtureTemplate.create installs checkly tarball as devDependency
- Remove symlinkChecklyPackage and Windows .cmd shim
- Replace installPackages: false with template: 'bare'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Every sandbox now uses a template (defaults to 'bare'). Remove
installPackages option and clean up redundant template: 'bare' from
all test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents pnpm pack in CLI tests from deleting dist/ while create-CLI
tests run in parallel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevent CI env vars from leaking into CLI subprocesses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sorccu sorccu force-pushed the simo/sim-244-switch-cli-from-npm-to-pnpm branch from 327296c to 89e890a Compare May 19, 2026 15:30
sorccu and others added 8 commits May 20, 2026 00:55
The fixture's playwright.config.ts imports from @playwright/test.
With extendEnv: false the subprocess can't resolve it from the
workspace. Add a minimal mock that implements defineConfig and devices.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
shell: true on Windows causes cmd.exe to mangle arguments with spaces.
Not needed since pnpm is invoked directly via execa.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The login command binds port 4242 for the OAuth callback. When tests
time out and kill the process, the port may not be immediately
available for the next test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce forceKillAfterDelay from default 5s to 1s so the port is
released faster. Increase test timeouts to accommodate the afterEach
port wait.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Windows, execa kills pnpm but the grandchild node process holding
port 4242 survives. Use netstat + taskkill /T to find and kill it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use detached process group + taskkill /T (Windows) or negative PID
SIGKILL (Unix) to kill pnpm and all its grandchild processes that
hold port 4242.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
detached: true on Windows breaks stdio for grandchild processes due
to DETACHED_PROCESS nullifying standard handles. Use detached only
on Unix (for process group kill) and taskkill /T on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Attach rejection handler immediately to prevent unhandled rejection
when taskkill kills the process tree externally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sorccu sorccu merged commit 2d2b13a into next/v8 May 20, 2026
8 checks passed
@sorccu sorccu deleted the simo/sim-244-switch-cli-from-npm-to-pnpm branch May 20, 2026 07:23
sorccu added a commit that referenced this pull request May 21, 2026
* feat!: switch from npm to pnpm

BREAKING CHANGE: The project now uses pnpm as its package manager.

- Replace package-lock.json with pnpm-lock.yaml (imported via pnpm import)
- Add pnpm-workspace.yaml for workspace configuration
- Update all CI workflows to use pnpm
- Update all npm scripts to use pnpm equivalents
- Update simple-git-hooks to use pnpm exec
- Add pnpm.onlyBuiltDependencies for esbuild and simple-git-hooks
- Replace fixture npm lockfiles with pnpm lockfiles
- Update test expectations for pnpm-lock.yaml in bundled file lists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use pnpm instead of npx in test fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add string-width and ast-types as explicit dependencies

These were phantom dependencies (transitive via recast and other packages)
that worked with npm's flat node_modules but fail under pnpm's strict
dependency resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: serialize pnpm lifecycle scripts to prevent race conditions

Set child-concurrency=1 in .npmrc so pnpm runs workspace prepare
scripts sequentially. Remove the redundant `pnpm -r run prepare`
from the root prepare script (pnpm already runs each package's
prepare hook) and move prepare:ai-context to postprepare so it
runs after all packages are built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): convert check-parse-error e2e test to use FixtureSandbox

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test(create-cli): log stderr when bootstrap e2e stdout is empty

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): force npm in e2e tests to avoid pnpm workspace detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): fix playwright config e2e test prompt injection

The test injected initializeGit=true but didn't account for when
.git already existed (skipping the prompt). Change to not init git
since it's not what the test is verifying, and add the missing
askCopyPlaywrightProject prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): stop injecting jiti into scaffolded project dependencies

jiti is now bundled internally by the CLI and no longer needed as a
user-facing dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): update pw-test e2e assertions for pnpm testCommand

Fixtures now detect pnpm as the package manager, so the generated
testCommand is 'pnpm playwright test' instead of 'npx playwright test'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: decouple skills/ sync from prepare lifecycle

Move the root-level skills/ copy from a postprepare lifecycle hook to
an explicit sync:skills script. This eliminates the cross-package
dependency between root and packages/cli during pnpm install, removing
the need for child-concurrency=1 in .npmrc.

The AI context is still built as part of packages/cli's prepare script
(needed for the published tarball), but the root no longer races to
copy from its output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): optimize test fixtures with FixtureTemplate

Introduce FixtureTemplate to pre-install dependencies once and share
them across fixtures via symlinks, reducing pnpm install calls from
53 to 1.

- Add FixtureTemplate class that caches pre-installed node_modules
- Add vitest globalSetup to build the playwright template once
- Migrate playwright-check, parse-files tests to use template
- Set installPackages: false for fixtures with no deps (agentic-check,
  api-check, browser-check, project-parser)
- Symlink workspace checkly package into all fixture node_modules
- Remove injectPackedSelf (dead code) and pnpm pack from test scripts
- Remove accidentally committed node_modules from test-bundling and
  test-shared-bundling fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): use FixtureTemplate in e2e tests

Share a single playwright install across all e2e fixture sandboxes
via symlinked node_modules. Fixtures with no dependencies use
installPackages: false instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use pnpm in e2e tests and add lockfiles to fixtures

Replace npx with pnpm in e2e test runners for consistency with the
pnpm-based fixtures. Add pnpm-lock.yaml to all e2e fixtures so
detectPackageManager reliably identifies pnpm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): add FixtureTemplate.use() and simplify template usage

Add FixtureTemplate.use() which looks up a cached template by name,
falling back to an env var set by globalSetup for cross-process
communication. Test files now pass template: 'playwright' as a string
instead of managing FixtureTemplate.create() calls directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use dedicated template for pinned playwright version in pw-test

The test-pwt-native fixture pins @playwright/test to 1.53.1. The shared
playwright template installs ^1.59.1 which resolves to a newer version,
causing a version mismatch error at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): create fixture templates serially for better cache reuse

Sequential pnpm installs let the second template reuse packages
cached by the first (e.g. playwright-core), avoiding redundant
downloads on CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): prepare FixtureSandbox for runChecklyCli migration

- Make source param optional (empty sandbox when omitted)
- Add 'bare' template (checkly only, no other deps)
- Fix Windows .bin by writing a .cmd shim instead of a symlink
- Replace runChecklyCli with checklyEnv + runCheckly helpers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): migrate all e2e tests from runChecklyCli to FixtureSandbox

Replace the raw child_process.spawn-based runChecklyCli with
FixtureSandbox + runCheckly helper across all 21 e2e test files.

Tests now use pnpm checkly via the .bin symlink instead of spawning
bin/run directly, which fixes Windows module resolution issues with
pnpm's node_modules layout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): write package.json in sourceless fixture sandboxes

pnpm requires a package.json in the working directory. When no source
is provided, write a minimal one so pnpm checkly can run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): fix e2e test migration issues

- destroy: wrong project name exits 0, not failure
- login: remove trailing newline assertion (oclif line-wrapping)
- switch: remove trailing newline assertion
- env.rm: add explicit timeout for interactive prompt test
- Add missing package.json to fixtures that lacked one
- Write package.json in sourceless sandboxes for pnpm compat

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): unset CI env var in e2e test helper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): force interactive CLI mode in e2e tests

Use CHECKLY_CLI_MODE=interactive instead of unsetting CI, since
the CLI also checks GITHUB_ACTIONS and other CI-specific env vars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add .js extension to oclif helpClass path

On Windows, oclif's module-loader uses require() to load the custom
help class. Without the .js extension, require() fails to resolve
the module in an ESM package because Node.js doesn't auto-append
extensions for require() in "type": "module" packages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): run CLI via node instead of pnpm in e2e tests

On Windows, pnpm's import() of oclif command modules fails with
MODULE_NOT_FOUND even when the files exist. Bypass pnpm's execution
layer by invoking node with the bin/run path directly, matching the
behavior of the old runChecklyCli helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use real CLI path instead of junction path in e2e tests

On Windows, Node.js import() fails when resolving through NTFS
junctions. Use CLI_PACKAGE_ROOT directly to avoid junction traversal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use stripped env in e2e tests to match old runChecklyCli

Use extendEnv: false so the CLI subprocess gets only explicitly passed
env vars, matching the old child_process.spawn behavior. This prevents
CI runner env vars from interfering with the CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): pass API keys via checklyEnv in direct fixt.run callers

Tests using fixt.run directly need checklyEnv() to provide API keys
and other required env vars when extendEnv is false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use dir symlinks instead of junctions on Windows

NTFS junctions cause Node.js ESM import() to fail when resolving
modules through the junction. Regular dir symlinks work correctly
on GitHub Actions runners which have the required permissions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add missing deps to e2e fixture templates

Add uuid to the playwright template (used by deploy-project fixture).
Switch sync-playwright tests from bare to playwright template (fixture
loads playwright.config.ts which imports @playwright/test).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use shell on Windows in FixtureSandbox.run

Matches the old runChecklyCli behavior which used shell: true on
Windows for cmd.exe to handle process execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): switch e2e tests back to pnpm checkly

Unit tests use pnpm checkly and pass on Windows. The node bin/run
approach fails because oclif's CJS module-loader can't import()
ESM command files using Windows absolute paths. With dir symlinks
(not junctions) now in place, pnpm checkly should work correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove extendEnv: false from e2e tests

Node.js on Windows needs system env vars (SYSTEMROOT, etc.) for
module resolution. Stripping the env caused import() to fail for
some files. Use the default extendEnv: true and rely on
CHECKLY_CLI_MODE: 'interactive' to handle CI detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): install packed CLI tarball into templates instead of symlinking

Windows CI runners have broken pnpm junctions that cause import() to
fail. Install the packed CLI tarball into each FixtureTemplate via
pnpm install, giving real file copies instead of junctions.

- Add pnpm pack back to test scripts
- FixtureTemplate.create installs checkly tarball as devDependency
- Remove symlinkChecklyPackage and Windows .cmd shim
- Replace installPackages: false with template: 'bare'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): remove installPackages option, default template to bare

Every sandbox now uses a template (defaults to 'bare'). Remove
installPackages option and clean up redundant template: 'bare' from
all test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): split e2e tests into separate jobs per package

Prevents pnpm pack in CLI tests from deleting dist/ while create-CLI
tests run in parallel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: cancel in-progress workflow runs on new push

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: use 'e2e - <package> - <os>' job name format

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use extendEnv: false in e2e test helpers

Prevent CI env vars from leaking into CLI subprocesses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): add mock @playwright/test to playwright-project fixture

The fixture's playwright.config.ts imports from @playwright/test.
With extendEnv: false the subprocess can't resolve it from the
workspace. Add a minimal mock that implements defineConfig and devices.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove shell: true from FixtureSandbox.run

shell: true on Windows causes cmd.exe to mangle arguments with spaces.
Not needed since pnpm is invoked directly via execa.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): wait for port 4242 release between login e2e tests

The login command binds port 4242 for the OAuth callback. When tests
time out and kill the process, the port may not be immediately
available for the next test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): force-kill login process after 1s grace period

Reduce forceKillAfterDelay from default 5s to 1s so the port is
released faster. Increase test timeouts to accommodate the afterEach
port wait.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): kill orphaned login process on Windows via taskkill

On Windows, execa kills pnpm but the grandchild node process holding
port 4242 survives. Use netstat + taskkill /T to find and kill it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): kill entire process tree in login e2e tests

Use detached process group + taskkill /T (Windows) or negative PID
SIGKILL (Unix) to kill pnpm and all its grandchild processes that
hold port 4242.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use detached only on Unix in login tests

detached: true on Windows breaks stdio for grandchild processes due
to DETACHED_PROCESS nullifying standard handles. Use detached only
on Unix (for process group kill) and taskkill /T on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): handle subprocess rejection in login tests

Attach rejection handler immediately to prevent unhandled rejection
when taskkill kills the process tree externally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sorccu sorccu mentioned this pull request May 22, 2026
sorccu added a commit that referenced this pull request May 22, 2026
* feat!: switch from npm to pnpm

BREAKING CHANGE: The project now uses pnpm as its package manager.

- Replace package-lock.json with pnpm-lock.yaml (imported via pnpm import)
- Add pnpm-workspace.yaml for workspace configuration
- Update all CI workflows to use pnpm
- Update all npm scripts to use pnpm equivalents
- Update simple-git-hooks to use pnpm exec
- Add pnpm.onlyBuiltDependencies for esbuild and simple-git-hooks
- Replace fixture npm lockfiles with pnpm lockfiles
- Update test expectations for pnpm-lock.yaml in bundled file lists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use pnpm instead of npx in test fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add string-width and ast-types as explicit dependencies

These were phantom dependencies (transitive via recast and other packages)
that worked with npm's flat node_modules but fail under pnpm's strict
dependency resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: serialize pnpm lifecycle scripts to prevent race conditions

Set child-concurrency=1 in .npmrc so pnpm runs workspace prepare
scripts sequentially. Remove the redundant `pnpm -r run prepare`
from the root prepare script (pnpm already runs each package's
prepare hook) and move prepare:ai-context to postprepare so it
runs after all packages are built.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): convert check-parse-error e2e test to use FixtureSandbox

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test(create-cli): log stderr when bootstrap e2e stdout is empty

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): force npm in e2e tests to avoid pnpm workspace detection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): fix playwright config e2e test prompt injection

The test injected initializeGit=true but didn't account for when
.git already existed (skipping the prompt). Change to not init git
since it's not what the test is verifying, and add the missing
askCopyPlaywrightProject prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): stop injecting jiti into scaffolded project dependencies

jiti is now bundled internally by the CLI and no longer needed as a
user-facing dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): update pw-test e2e assertions for pnpm testCommand

Fixtures now detect pnpm as the package manager, so the generated
testCommand is 'pnpm playwright test' instead of 'npx playwright test'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: decouple skills/ sync from prepare lifecycle

Move the root-level skills/ copy from a postprepare lifecycle hook to
an explicit sync:skills script. This eliminates the cross-package
dependency between root and packages/cli during pnpm install, removing
the need for child-concurrency=1 in .npmrc.

The AI context is still built as part of packages/cli's prepare script
(needed for the published tarball), but the root no longer races to
copy from its output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): optimize test fixtures with FixtureTemplate

Introduce FixtureTemplate to pre-install dependencies once and share
them across fixtures via symlinks, reducing pnpm install calls from
53 to 1.

- Add FixtureTemplate class that caches pre-installed node_modules
- Add vitest globalSetup to build the playwright template once
- Migrate playwright-check, parse-files tests to use template
- Set installPackages: false for fixtures with no deps (agentic-check,
  api-check, browser-check, project-parser)
- Symlink workspace checkly package into all fixture node_modules
- Remove injectPackedSelf (dead code) and pnpm pack from test scripts
- Remove accidentally committed node_modules from test-bundling and
  test-shared-bundling fixtures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): use FixtureTemplate in e2e tests

Share a single playwright install across all e2e fixture sandboxes
via symlinked node_modules. Fixtures with no dependencies use
installPackages: false instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use pnpm in e2e tests and add lockfiles to fixtures

Replace npx with pnpm in e2e test runners for consistency with the
pnpm-based fixtures. Add pnpm-lock.yaml to all e2e fixtures so
detectPackageManager reliably identifies pnpm.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): add FixtureTemplate.use() and simplify template usage

Add FixtureTemplate.use() which looks up a cached template by name,
falling back to an env var set by globalSetup for cross-process
communication. Test files now pass template: 'playwright' as a string
instead of managing FixtureTemplate.create() calls directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use dedicated template for pinned playwright version in pw-test

The test-pwt-native fixture pins @playwright/test to 1.53.1. The shared
playwright template installs ^1.59.1 which resolves to a newer version,
causing a version mismatch error at runtime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* perf(cli): create fixture templates serially for better cache reuse

Sequential pnpm installs let the second template reuse packages
cached by the first (e.g. playwright-core), avoiding redundant
downloads on CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): prepare FixtureSandbox for runChecklyCli migration

- Make source param optional (empty sandbox when omitted)
- Add 'bare' template (checkly only, no other deps)
- Fix Windows .bin by writing a .cmd shim instead of a symlink
- Replace runChecklyCli with checklyEnv + runCheckly helpers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): migrate all e2e tests from runChecklyCli to FixtureSandbox

Replace the raw child_process.spawn-based runChecklyCli with
FixtureSandbox + runCheckly helper across all 21 e2e test files.

Tests now use pnpm checkly via the .bin symlink instead of spawning
bin/run directly, which fixes Windows module resolution issues with
pnpm's node_modules layout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): write package.json in sourceless fixture sandboxes

pnpm requires a package.json in the working directory. When no source
is provided, write a minimal one so pnpm checkly can run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): fix e2e test migration issues

- destroy: wrong project name exits 0, not failure
- login: remove trailing newline assertion (oclif line-wrapping)
- switch: remove trailing newline assertion
- env.rm: add explicit timeout for interactive prompt test
- Add missing package.json to fixtures that lacked one
- Write package.json in sourceless sandboxes for pnpm compat

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): unset CI env var in e2e test helper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): force interactive CLI mode in e2e tests

Use CHECKLY_CLI_MODE=interactive instead of unsetting CI, since
the CLI also checks GITHUB_ACTIONS and other CI-specific env vars.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add .js extension to oclif helpClass path

On Windows, oclif's module-loader uses require() to load the custom
help class. Without the .js extension, require() fails to resolve
the module in an ESM package because Node.js doesn't auto-append
extensions for require() in "type": "module" packages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): run CLI via node instead of pnpm in e2e tests

On Windows, pnpm's import() of oclif command modules fails with
MODULE_NOT_FOUND even when the files exist. Bypass pnpm's execution
layer by invoking node with the bin/run path directly, matching the
behavior of the old runChecklyCli helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use real CLI path instead of junction path in e2e tests

On Windows, Node.js import() fails when resolving through NTFS
junctions. Use CLI_PACKAGE_ROOT directly to avoid junction traversal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use stripped env in e2e tests to match old runChecklyCli

Use extendEnv: false so the CLI subprocess gets only explicitly passed
env vars, matching the old child_process.spawn behavior. This prevents
CI runner env vars from interfering with the CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): pass API keys via checklyEnv in direct fixt.run callers

Tests using fixt.run directly need checklyEnv() to provide API keys
and other required env vars when extendEnv is false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use dir symlinks instead of junctions on Windows

NTFS junctions cause Node.js ESM import() to fail when resolving
modules through the junction. Regular dir symlinks work correctly
on GitHub Actions runners which have the required permissions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): add missing deps to e2e fixture templates

Add uuid to the playwright template (used by deploy-project fixture).
Switch sync-playwright tests from bare to playwright template (fixture
loads playwright.config.ts which imports @playwright/test).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use shell on Windows in FixtureSandbox.run

Matches the old runChecklyCli behavior which used shell: true on
Windows for cmd.exe to handle process execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): switch e2e tests back to pnpm checkly

Unit tests use pnpm checkly and pass on Windows. The node bin/run
approach fails because oclif's CJS module-loader can't import()
ESM command files using Windows absolute paths. With dir symlinks
(not junctions) now in place, pnpm checkly should work correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove extendEnv: false from e2e tests

Node.js on Windows needs system env vars (SYSTEMROOT, etc.) for
module resolution. Stripping the env caused import() to fail for
some files. Use the default extendEnv: true and rely on
CHECKLY_CLI_MODE: 'interactive' to handle CI detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): install packed CLI tarball into templates instead of symlinking

Windows CI runners have broken pnpm junctions that cause import() to
fail. Install the packed CLI tarball into each FixtureTemplate via
pnpm install, giving real file copies instead of junctions.

- Add pnpm pack back to test scripts
- FixtureTemplate.create installs checkly tarball as devDependency
- Remove symlinkChecklyPackage and Windows .cmd shim
- Replace installPackages: false with template: 'bare'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor(cli): remove installPackages option, default template to bare

Every sandbox now uses a template (defaults to 'bare'). Remove
installPackages option and clean up redundant template: 'bare' from
all test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): split e2e tests into separate jobs per package

Prevents pnpm pack in CLI tests from deleting dist/ while create-CLI
tests run in parallel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: cancel in-progress workflow runs on new push

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: use 'e2e - <package> - <os>' job name format

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use extendEnv: false in e2e test helpers

Prevent CI env vars from leaking into CLI subprocesses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(create-cli): add mock @playwright/test to playwright-project fixture

The fixture's playwright.config.ts imports from @playwright/test.
With extendEnv: false the subprocess can't resolve it from the
workspace. Add a minimal mock that implements defineConfig and devices.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): remove shell: true from FixtureSandbox.run

shell: true on Windows causes cmd.exe to mangle arguments with spaces.
Not needed since pnpm is invoked directly via execa.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): wait for port 4242 release between login e2e tests

The login command binds port 4242 for the OAuth callback. When tests
time out and kill the process, the port may not be immediately
available for the next test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): force-kill login process after 1s grace period

Reduce forceKillAfterDelay from default 5s to 1s so the port is
released faster. Increase test timeouts to accommodate the afterEach
port wait.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): kill orphaned login process on Windows via taskkill

On Windows, execa kills pnpm but the grandchild node process holding
port 4242 survives. Use netstat + taskkill /T to find and kill it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): kill entire process tree in login e2e tests

Use detached process group + taskkill /T (Windows) or negative PID
SIGKILL (Unix) to kill pnpm and all its grandchild processes that
hold port 4242.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use detached only on Unix in login tests

detached: true on Windows breaks stdio for grandchild processes due
to DETACHED_PROCESS nullifying standard handles. Use detached only
on Unix (for process group kill) and taskkill /T on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): handle subprocess rejection in login tests

Attach rejection handler immediately to prevent unhandled rejection
when taskkill kills the process tree externally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant